package com.firmboy.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 数据库连接的一个连接池
 *
 * @author firmboy
 * @create 2018-04-15 下午7:08
 **/
public class DBPool {

    //写个连接池的话，每次获取连接都是通过连接池获取，用完之后就要还回这个池子中区
    //第一个问题：用什么作为这个池子，list？map？还是数组
    //我绝得可以考虑用队列来作为池子，原因是这样，队列的一个特性就是先进先出，维持一个池子，每次用完之后就就将他放入到队列的
    //最后面，这样每次取的就是未被使用的连接，如果取不到链接了，那么说明池子里没有可用的链接了，这个时候1是考虑抛出异常，
    //2是考虑创建新的链接
    //第二个问题：怎样获取链接，这个地方可以考虑线程池的实现方式，将线程的创建交给一个连接工厂，这样就能保证程序的扩展性
    //第三个问题：要维持多少个链接，这个可以考虑在线程归还的时候判断一下队列里的数量，如果数量已经满足要求，就可以将当前要归还的
    //链接直接关闭

    /**
     *创建一个能放10个链接的队列
     */
    private ArrayBlockingQueue<Connection> queue = new ArrayBlockingQueue<Connection>(count);

    /**
     * 默认的创建队列的长度
     */
    private static int count = 10;

    private static String path = "db.propertis";

    private DBResource dbResource;

    private int curCount;


    DBPool(int count, String path){
        this.curCount = count;
        DBPool.count = count;
        DBPool.path = path;
        dbResource = DBResource.getResource(path);
        try{
            for (int i =0;i<count;i++){
                Connection connection = getConnection(dbResource);
                queue.put(connection);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }




    /**
     * 从链接池中获取连接，如果没有，就直接创建一个连接
     * @return
     */
    public synchronized Connection getConnection(){
        Connection poll = queue.poll();
        if(poll!=null){

        }else {
            System.out.println("加1");
            curCount++;
            poll =  getConnection(dbResource);
        }
        System.out.println(Thread.currentThread().getName());
        System.out.println("get当前线程池中线程数量："+curCount);
        return poll;
    }

    /**
     * 归还连接，如果队列中超过设定的则直接关闭连接，如果没有则放入队列中
     * @param connection
     */
    public synchronized void close(Connection connection){
        try{
            if(queue.size()>=count){

                System.out.println(queue.size()+"减1");
                curCount--;
                connection.close();
            }else{
                queue.put(connection);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName());
        System.out.println("close当前线程池中线程数量："+curCount);
    }


    /**
     * 获取新链接
     * @param dbResource
     * @return
     */
    private Connection getConnection(DBResource dbResource){
        Connection connection = null;
        try{
            Class.forName(dbResource.getDriverClass());
            connection = DriverManager.getConnection(dbResource.getUrl(), dbResource.getUserName(), dbResource.getPassWord());
        }catch(Exception e){
            e.printStackTrace();
        }
        return connection;
    }

}
